﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using FikriKibar.Business.Abstract;
using FikriKibar.Common.Entities;
using FikriKibar.Common.Exceptions;
using FikriKibar.Common.Helpers;
using FikriKibar.Common.Validation.FluentValidation.ContentType;
using FikriKibar.DataAccess;
using FikriKibar.DataAccess.Abstract;
using FikriKibar.Entities.Abstract;
using FikriKibar.Entities.Composite.BaseModels;
using FikriKibar.Entities.Concrete;
using FikriKibar.Globalization;

namespace FikriKibar.Business.Concrete
{
    public class ContentTypeManager : IContentTypeService
    {
        #region Global Declarations

        private readonly IContentTypeDal _contentTypeDal = new EfContentTypeDal();

        private readonly IContentTypeLanguageLineDal _contentTypeLanguageLineDal = new EfContentTypeLanguageLineDal();

        private readonly IContentTypeLanguageLineHistoryDal _contentTypeLanguageLineHistoryDal = new EfContentTypeLanguageLineHistoryDal();

        private readonly IContentTypeHistoryDal _contentTypeHistoryDal = new EfContentTypeHistoryDal();

        private readonly ILanguageDal _languageDal = new EfLanguageDal();

        private readonly ISettingDal _settingDal = new EfSettingDal();

        #endregion

        #region Methods

        public AddModel<ContentTypeLanguageLine> Add()
        {
            return new AddModel<ContentTypeLanguageLine>
            {
                LanguageList = _languageDal.Filter(e => e.IsApproved)
            };
        }
        public void Add(AddModel<ContentTypeLanguageLine> model)
        {
            var validator = new AddValidator(model);
            var contentTypeLanguageLine = model.Item;
            var validationResults = validator.Validate();
            if (!validator.IsValid)
            {
                throw new ValidationException(Resources.InvalidEntityMessage)
                {
                    ValidationResult = validationResults
                };
            }
            var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;


            var contentType = new ContentType
            {
                CreateDate = DateTime.Now,
                CreatedBy = fikriKibarIdentity.UserId,
                UpdatedBy = fikriKibarIdentity.UserId,
                UpdateDate = DateTime.Now

            };

            var addedContentType = _contentTypeDal.Add(contentType);

            foreach (var languageId in model.SelectedLanguageIds)
            {
                contentTypeLanguageLine.ContentTypeId = addedContentType.Id;
                contentTypeLanguageLine.ContentType = null;
                contentTypeLanguageLine.LanguageId = languageId;
                contentTypeLanguageLine.ContentTypeName = model.Item.ContentTypeName;
                contentTypeLanguageLine.ContentTypeDescription = model.Item.ContentTypeDescription;
                contentTypeLanguageLine.CreatedBy = fikriKibarIdentity.UserId;
                contentTypeLanguageLine.CreateDate = DateTime.Now;
                contentTypeLanguageLine.UpdatedBy = fikriKibarIdentity.UserId;
                contentTypeLanguageLine.UpdateDate = DateTime.Now;
                contentTypeLanguageLine.PublishBeginDate = model.Item.PublishBeginDate;
                contentTypeLanguageLine.PublishEndDate = model.Item.PublishEndDate;
                contentTypeLanguageLine.DisplayOrder = addedContentType.Id;
                contentTypeLanguageLine.IsApproved = model.Item.IsApproved;
                _contentTypeLanguageLineDal.Add(contentTypeLanguageLine);
            }
        }
        public UpdateModel<ContentTypeLanguageLine> Update(int id, string language)
        {
            var contentTypeLanguageLine = _contentTypeLanguageLineDal.Filter(e => e.ContentTypeId == id && e.Language.LanguageCode == language).FirstOrDefault();

            if (contentTypeLanguageLine == null) throw new NotFoundException();
            return new UpdateModel<ContentTypeLanguageLine>
            {
                LanguageList = _languageDal.Filter(e => e.IsApproved),
                SelectedLanguageCode = language,
                ItemId = id,
                Item = contentTypeLanguageLine
            };
        }
        public void Update(UpdateModel<ContentTypeLanguageLine> model)
        {
            var validator = new UpdateValidator(model);
            var validationResults = validator.Validate();
            if (!validator.IsValid)
            {
                throw new ValidationException(Resources.InvalidEntityMessage)
                {
                    ValidationResult = validationResults
                };
            }
            var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;

            var contentType = _contentTypeDal.GetById(model.ItemId);

            var contentTypeHistory = new ContentTypeHistory
            {
                ContentTypeId = contentType.Id,
                CreateDate = contentType.CreateDate,
                CreatedBy = contentType.CreatedBy,
                UpdateDate = contentType.UpdateDate,
                UpdatedBy = contentType.UpdatedBy,
                IsDeleted = false
            };
            _contentTypeHistoryDal.Add(contentTypeHistory);


            contentType.UpdateDate = DateTime.Now;
            contentType.UpdatedBy = fikriKibarIdentity.UserId;
            var affectedContentType = _contentTypeDal.Update(contentType);

            var contentTypeLanguageLine = _contentTypeLanguageLineDal.Filter(e => e.ContentTypeId == model.ItemId && e.Language.LanguageCode == model.SelectedLanguageCode).FirstOrDefault();

            if (contentTypeLanguageLine == null)
            {
                contentTypeLanguageLine = new ContentTypeLanguageLine
                {
                    ContentTypeId = affectedContentType.Id,
                    ContentType = null,
                    LanguageId = _languageDal.GetByCode(model.SelectedLanguageCode).Id,
                    ContentTypeName = model.Item.ContentTypeName,
                    ContentTypeDescription = model.Item.ContentTypeDescription,
                    CreatedBy = fikriKibarIdentity.UserId,
                    CreateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    UpdateDate = DateTime.Now,
                    PublishBeginDate = model.Item.PublishBeginDate,
                    PublishEndDate = model.Item.PublishEndDate,
                    DisplayOrder = affectedContentType.Id,
                    IsApproved = model.Item.IsApproved
                };
                _contentTypeLanguageLineDal.Add(contentTypeLanguageLine);

            }
            else
            {
                var contentTypeLanguageLineHistory = new ContentTypeLanguageLineHistory
                {
                    ContentTypeLanguageLineId = contentTypeLanguageLine.Id,
                    ContentTypeId = contentTypeLanguageLine.ContentTypeId,
                    LanguageId = contentTypeLanguageLine.LanguageId,
                    ContentTypeName = contentTypeLanguageLine.ContentTypeName,
                    ContentTypeDescription = contentTypeLanguageLine.ContentTypeDescription,
                    CreateDate = contentTypeLanguageLine.CreateDate,
                    CreatedBy = contentType.CreatedBy,
                    UpdateDate = contentType.UpdateDate,
                    UpdatedBy = contentType.UpdatedBy,
                    PublishBeginDate = contentTypeLanguageLine.PublishBeginDate,
                    PublishEndDate = contentTypeLanguageLine.PublishEndDate,
                    DisplayOrder = contentTypeLanguageLine.DisplayOrder,
                    IsApproved = contentTypeLanguageLine.IsApproved,
                    IsDeleted = false
                };
                _contentTypeLanguageLineHistoryDal.Add(contentTypeLanguageLineHistory);

                contentTypeLanguageLine.UpdateDate = DateTime.Now;
                contentTypeLanguageLine.UpdatedBy = fikriKibarIdentity.UserId;
                contentTypeLanguageLine.ContentTypeName = model.Item.ContentTypeName;
                contentTypeLanguageLine.ContentTypeDescription = model.Item.ContentTypeDescription;
                contentTypeLanguageLine.PublishBeginDate = model.Item.PublishBeginDate;
                contentTypeLanguageLine.PublishEndDate = model.Item.PublishEndDate;
                contentTypeLanguageLine.IsApproved = model.Item.IsApproved;

                _contentTypeLanguageLineDal.Update(contentTypeLanguageLine);
            }




        }
        public ListModel<ContentTypeLanguageLine> GetList(string searchTerm, string languageCode, int status, int index, int size, string idsForSort, string idsForApprove, string idsForDelete)
        {
            var model = new ListModel<ContentTypeLanguageLine>
            {
                Paging = new Paging(),
                ItemList = new List<ContentTypeLanguageLine>(),
                LanguageList = _languageDal.Filter(e => e.IsApproved)
            };

            if (idsForDelete != null)
            {
                var ids = idsForDelete;
                ids = ids.Remove(ids.Length - 1);
                var idArray = ids.Split(',');
                var idList = idArray.Select(id => id.ConvertToInt()).ToList();
                DeleteSelected(idList, languageCode);

            }
            model.IdsForDelete = null;


            if (idsForApprove != null)
            {
                var ids = idsForApprove;
                ids = ids.Remove(ids.Length - 1);
                var idArray = ids.Split(',');
                var idList = idArray.Select(id => id.ConvertToInt()).ToList();
                ApproveSelected(idList, languageCode);
            }

            model.IdsForApprove = null;

            var sortHelper = new SortHelper<ContentTypeLanguageLine>();
            sortHelper.OrderByDescending(t => t.DisplayOrder);

            model.Paging.CurrentPageSize = size;
            model.Paging.CurrentPage = index;
            model.SelectedStatus = status;

            if (status != -1)
            {
                var blStatus = status.ToString().ConvertToBoolean();
                model.Paging.TotalItemCount = _contentTypeLanguageLineDal.GetTotalCount(e => e.ContentTypeName.Contains(searchTerm) && e.Language.LanguageCode == languageCode && e.IsApproved == blStatus);
            }
            else
            {
                model.Paging.TotalItemCount = _contentTypeLanguageLineDal.GetTotalCount(e => e.ContentTypeName.Contains(searchTerm) && e.Language.LanguageCode == languageCode);
            }

            var pageSizeListSetting = _settingDal.GetValueByKey("PageSizeList");
            var pageSizeSettingValue = "10,25,50,100";
            if (pageSizeListSetting != null)
            {
                pageSizeSettingValue = pageSizeListSetting;
            }
            var pageSizeList = pageSizeSettingValue.Split(',').Select(t => new KeyValuePair<int, string>(t.ConvertToInt(), t)).ToList();

            pageSizeList.Insert(0, new KeyValuePair<int, string>(-1, "[" + Resources.All + "]"));
            model.Paging.PageSizeList = pageSizeList;


            if (status != -1)
            {
                var blStatus = status.ToString().ConvertToBoolean();
                model.ItemList = model.Paging.CurrentPageSize > 0 ? _contentTypeLanguageLineDal.Filter(e => e.ContentTypeName.Contains(searchTerm) && e.Language.LanguageCode == languageCode && e.IsApproved == blStatus, sortHelper, index, size) : _contentTypeLanguageLineDal.Filter(e => e.ContentTypeName.Contains(searchTerm) && e.Language.LanguageCode == languageCode && e.IsApproved == blStatus);
            }
            else
            {
                model.ItemList = model.Paging.CurrentPageSize > 0 ? _contentTypeLanguageLineDal.Filter(e => e.ContentTypeName.Contains(searchTerm) && e.Language.LanguageCode == languageCode, sortHelper, index, size) : _contentTypeLanguageLineDal.Filter(e => e.ContentTypeName.Contains(searchTerm) && e.Language.LanguageCode == languageCode);
            }


            if (idsForSort != null)
            {
                var ids = idsForSort;
                ids = ids.Remove(ids.Length - 1);
                var idArray = ids.Split(',');
                var idList = idArray.Select(id => id.ConvertToInt()).ToList();
                model.ItemList = SaveSort(idList, languageCode);
            }
            model.IdsForSort = null;

            model.Searched = searchTerm;
            model.SelectedLanguageCode = languageCode;

            model.Paging.CurrentPage = index;
            model.Paging.TotalPageCount = (int)Math.Ceiling((float)model.Paging.TotalItemCount / size);
            return model;
        }
        public void Delete(int id, string language)
        {
            var contentTypeLanguageLine = _contentTypeLanguageLineDal.Filter(e => e.Language.LanguageCode == language).FirstOrDefault(e => e.ContentType.Id == id);
            if (contentTypeLanguageLine == null) return;
            var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;
            var contentTypeLanguageLineHistory = new ContentTypeLanguageLineHistory
            {
                ContentTypeLanguageLineId = contentTypeLanguageLine.Id,
                ContentTypeId = contentTypeLanguageLine.ContentTypeId,
                LanguageId = contentTypeLanguageLine.LanguageId,
                ContentTypeName = contentTypeLanguageLine.ContentTypeName,
                ContentTypeDescription = contentTypeLanguageLine.ContentTypeDescription,
                CreateDate = contentTypeLanguageLine.CreateDate,
                CreatedBy = contentTypeLanguageLine.CreatedBy,
                UpdateDate = DateTime.Now,
                UpdatedBy = fikriKibarIdentity.UserId,
                PublishBeginDate = contentTypeLanguageLine.PublishBeginDate,
                PublishEndDate = contentTypeLanguageLine.PublishEndDate,
                DisplayOrder = contentTypeLanguageLine.DisplayOrder,
                IsApproved = contentTypeLanguageLine.IsApproved,
                IsDeleted = true
            };
            _contentTypeLanguageLineHistoryDal.Add(contentTypeLanguageLineHistory);
            _contentTypeLanguageLineDal.Delete(contentTypeLanguageLine);

            if (_contentTypeLanguageLineDal.Filter(e => e.ContentTypeId == id).Any()) return;
            var contentType = _contentTypeDal.GetById(id);
            if (contentType == null) return;
            var contentTypeHistory = new ContentTypeHistory
            {
                ContentTypeId = contentType.Id,
                CreateDate = contentType.CreateDate,
                CreatedBy = contentType.CreatedBy,
                UpdateDate = DateTime.Now,
                UpdatedBy = fikriKibarIdentity.UserId,
                IsDeleted = true
            };
            _contentTypeHistoryDal.Add(contentTypeHistory);
            _contentTypeDal.Delete(contentType);
        }
        private List<ContentTypeLanguageLine> SaveSort(IReadOnlyList<int> idList, string languageCode)
        {
            var returnedValue = new List<ContentTypeLanguageLine>();
            for (var i = 0; i < idList.Count; i++)
            {
                var contentTypeLanguageLine = _contentTypeLanguageLineDal.Filter(e => e.Language.LanguageCode == languageCode).FirstOrDefault(e => e.ContentType.Id == idList[i]);

                if (contentTypeLanguageLine == null) continue;
                var contentType = _contentTypeDal.GetById(contentTypeLanguageLine.ContentType.Id);
                var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;

                var contentTypeHistory = new ContentTypeHistory
                {
                    ContentTypeId = contentType.Id,
                    CreateDate = contentType.CreateDate,
                    CreatedBy = contentType.CreatedBy,
                    UpdateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    IsDeleted = false
                };
                _contentTypeHistoryDal.Add(contentTypeHistory);


                contentType.UpdatedBy = fikriKibarIdentity.UserId;
                contentType.UpdateDate = DateTime.Now;
                _contentTypeDal.Update(contentType);

                var contentTypeLanguageLineHistory = new ContentTypeLanguageLineHistory
                {
                    ContentTypeLanguageLineId = contentTypeLanguageLine.Id,
                    ContentTypeId = contentTypeLanguageLine.ContentTypeId,
                    LanguageId = contentTypeLanguageLine.LanguageId,
                    ContentTypeName = contentTypeLanguageLine.ContentTypeName,
                    ContentTypeDescription = contentTypeLanguageLine.ContentTypeDescription,
                    CreateDate = contentTypeLanguageLine.CreateDate,
                    CreatedBy = contentTypeLanguageLine.CreatedBy,
                    UpdateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    PublishBeginDate = contentTypeLanguageLine.PublishBeginDate,
                    PublishEndDate = contentTypeLanguageLine.PublishEndDate,
                    DisplayOrder = contentTypeLanguageLine.DisplayOrder,
                    IsApproved = contentTypeLanguageLine.IsApproved,
                    IsDeleted = false
                };
                _contentTypeLanguageLineHistoryDal.Add(contentTypeLanguageLineHistory);


                contentTypeLanguageLine.DisplayOrder = i + 1;
                contentTypeLanguageLine.UpdatedBy = fikriKibarIdentity.UserId;
                contentTypeLanguageLine.UpdateDate = DateTime.Now;
                contentTypeLanguageLine.ContentType = contentType;
                _contentTypeLanguageLineDal.Update(contentTypeLanguageLine);
                returnedValue.Add(contentTypeLanguageLine);
            }
            return returnedValue;
        }
        private void ApproveSelected(IEnumerable<int> idList, string languageCode)
        {
            foreach (var id in idList)
            {
                var contentTypeLanguageLine = _contentTypeLanguageLineDal.Filter(e => e.Language.LanguageCode == languageCode).FirstOrDefault(e => e.ContentType.Id == id);
                if (contentTypeLanguageLine == null) continue;
                var contentType = _contentTypeDal.GetById(contentTypeLanguageLine.ContentType.Id);
                var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;
                var contentTypeHistory = new ContentTypeHistory
                {
                    ContentTypeId = contentType.Id,
                    CreateDate = contentType.CreateDate,
                    CreatedBy = contentType.CreatedBy,
                    UpdateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    IsDeleted = false
                };
                _contentTypeHistoryDal.Add(contentTypeHistory);
                contentType.UpdatedBy = fikriKibarIdentity.UserId;
                contentType.UpdateDate = DateTime.Now;
                _contentTypeDal.Update(contentType);

                var contentTypeLanguageLineHistory = new ContentTypeLanguageLineHistory
                {
                    ContentTypeLanguageLineId = contentTypeLanguageLine.Id,
                    ContentTypeId = contentTypeLanguageLine.ContentTypeId,
                    LanguageId = contentTypeLanguageLine.LanguageId,
                    ContentTypeName = contentTypeLanguageLine.ContentTypeName,
                    ContentTypeDescription = contentTypeLanguageLine.ContentTypeDescription,
                    CreateDate = contentTypeLanguageLine.CreateDate,
                    CreatedBy = contentTypeLanguageLine.CreatedBy,
                    UpdateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    PublishBeginDate = contentTypeLanguageLine.PublishBeginDate,
                    PublishEndDate = contentTypeLanguageLine.PublishEndDate,
                    DisplayOrder = contentTypeLanguageLine.DisplayOrder,
                    IsApproved = contentTypeLanguageLine.IsApproved,
                    IsDeleted = false
                };
                _contentTypeLanguageLineHistoryDal.Add(contentTypeLanguageLineHistory);


                contentTypeLanguageLine.UpdatedBy = fikriKibarIdentity.UserId;
                contentTypeLanguageLine.UpdateDate = DateTime.Now;
                contentTypeLanguageLine.IsApproved = true;
                contentTypeLanguageLine.ContentType = contentType;
                _contentTypeLanguageLineDal.Update(contentTypeLanguageLine);

            }
        }
        private void DeleteSelected(IEnumerable<int> idList, string languageCode)
        {
            foreach (var id in idList)
            {
                Delete(id, languageCode);
            }
        }
    
        #endregion
    }
}
